/* eslint-disable @typescript-eslint/no-empty-function */
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable unicorn/no-array-for-each */
class Example {
  // property declarations are not part of ES6, though they are valid in TypeScript:
  @Reflect.metadata("custom:metadata", { metadata: "staticProperty" })
  static staticProperty: any;

  property: any;

  static staticMethod(p: any): void {}

  method(p: any): void {}
}

// property (on constructor)
Reflect.defineMetadata(
  "custom:define",
  { name: "staticProperty" },
  Example,
  "staticProperty",
);

// property (on prototype)
Reflect.defineMetadata(
  "custom:define",
  { name: "property" },
  Example.prototype,
  "property",
);

// method (on constructor)
Reflect.defineMetadata(
  "custom:define",
  { name: "staticMethod" },
  Example,
  "staticMethod",
);

// method (on prototype)
Reflect.defineMetadata(
  "custom:define",
  { name: "method" },
  Example.prototype,
  "method",
);

// decorator factory as metadata-producing define.
function define(options: object): PropertyDecorator {
  return (target, key) =>
    Reflect.defineMetadata("custom:define", options, target, key);
}
/// ////////////////////////////////////////////////////
/// ////////////////////////////////////////////////////
/// ////////////////////////////////////////////////////
const sp = Reflect.getMetadata("custom:define", Example, "staticProperty");
// => {name: 'staticProperty'}
const p = Reflect.getMetadata("custom:define", Example.prototype, "property");
// => {name: 'property'}
const sm = Reflect.getMetadata("custom:define", Example, "staticMethod");
// => {name: 'staticMethod'}
const m = Reflect.getMetadata("custom:define", Example.prototype, "method");
// => {name: 'method'}

[sp, p, sm, m].forEach((item: { name: string }) => {
  console.log(item.name);
});

const sp2: { metadata: string } = Reflect.getMetadata(
  "custom:define",
  Example,
  "staticProperty",
);
console.log(sp2.metadata);

export { Example };
